Skip to content

fix(librarypath): stop cleanEmpty from panicking on a non-trailing empty entry - #272

Merged
viniciussanchez merged 1 commit into
HashLoad:mainfrom
vBaggio:fix/cleanEmpty-slice-panic
Aug 10, 2026
Merged

fix(librarypath): stop cleanEmpty from panicking on a non-trailing empty entry#272
viniciussanchez merged 1 commit into
HashLoad:mainfrom
vBaggio:fix/cleanEmpty-slice-panic

Conversation

@vBaggio

@vBaggio vBaggio commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

O problema

boss install mata o processo com um panic no fim da instalação, depois que todas as dependências já foram resolvidas, baixadas e escritas em disco (boss.json, boss-lock.json e o .dproj já atualizados) — só quebra no passo final de "Updating library path":

♻️ Updating library path...
panic: runtime error: slice bounds out of range [:2:1]

goroutine 1 [running]:
slices.Delete[...](...)
	.../slices/slices.go:223
github.com/hashload/boss/utils/librarypath.cleanEmpty(...)
	.../utils/librarypath/librarypath.go:209
github.com/hashload/boss/utils/librarypath.getNewBrowsingPathsFromDir(...)
	.../utils/librarypath/librarypath.go:236
...
github.com/hashload/boss/internal/core/services/installer.DoInstall(...)
	.../internal/core/services/installer/core.go:135

Causa

cleanEmpty percorre paths com range e apaga elementos vazios via slices.Delete dentro do próprio loop:

func cleanEmpty(paths []string) []string {
	for index, value := range paths {
		if value == "" {
			paths = slices.Delete(paths, index, index+1)
		}
	}
	return paths
}

range paths fixa o tamanho da slice uma vez, no início do loop. Cada slices.Delete encolhe a slice de verdade, mas o loop continua contando contra o tamanho original. Basta existir uma string vazia que não seja o último elemento para o índice do range ultrapassar o tamanho já encolhido — daí o slice bounds out of range.

Reproduzi isso na mão, revertendo só essa função para testar ["a", "", "b"]:

--- FAIL: TestCleanEmpty/single_empty (0.00s)
panic: runtime error: slice bounds out of range [:3:2]
	slices.Delete[...](...)
	github.com/hashload/boss/utils/librarypath.cleanEmpty(...)

Mesmo panic, mesma função — confirma que não precisa de múltiplas entradas vazias, uma só (fora da última posição) já derruba.

cleanEmpty é chamado a partir de getNewBrowsingPathsFromDir, dentro de UpdateLibraryPath, que junta os browsing paths declarados no boss.json de cada dependência instalada num projeto. Qualquer "" que sobre nessa lista acumulada (antes da última posição) derruba o boss install inteiro nesse passo — mesmo com a instalação em si já ter dado certo.

A correção

Reescrevi como o filtro in-place idiomático em Go, sem mutar a slice enquanto itera sobre ela:

func cleanEmpty(paths []string) []string {
	cleaned := paths[:0]
	for _, value := range paths {
		if value != "" {
			cleaned = append(cleaned, value)
		}
	}
	return cleaned
}

Índice de escrita nunca ultrapassa o de leitura, então reaproveitar o array de trás (paths[:0]) é seguro. Removi também o import "slices", que ficou sem uso.

Rastreei os call sites (getNewPathsFromDir, getNewBrowsingPathsFromDirdproj_util.go / global_util_win.go): em todos, o retorno é reatribuído na mesma variável, então nenhum caller fica com uma slice obsoleta apontando pro array antigo.

Testes

  • TestCleanEmpty novo, cobrindo sem vazios, um vazio no meio, vários vazios e todos vazios — os dois últimos casos derrubavam a versão antiga.
  • go test ./utils/librarypath/... verde, sem regressão nos testes já existentes do pacote.
  • go build ./... e go vet ./... limpos.

🤖 Generated with Claude Code

…pty entry

range paths caches the slice length once at loop start, but slices.Delete
shrinks the backing slice on every match. As soon as one "" sits before the
last element, the loop keeps counting against the original length and calls
slices.Delete with an index past the now-shorter slice, panicking with
"slice bounds out of range".

boss install hits this in UpdateLibraryPath, while assembling the global
browsing path across every installed dependency's boss.json -- any accumulated
"" in that list before the final entry crashes the whole install after every
dependency already resolved and was written to disk.

Rewritten as the standard in-place filter (write index trailing the read
index), which stays correct while mutating the same backing array mid-range.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 8, 2026 22:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@6a60357). Learn more about missing BASE report.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #272   +/-   ##
=======================================
  Coverage        ?   28.59%           
=======================================
  Files           ?       90           
  Lines           ?     5701           
  Branches        ?        0           
=======================================
  Hits            ?     1630           
  Misses          ?     3932           
  Partials        ?      139           
Flag Coverage Δ
unittests 28.59% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@viniciussanchez
viniciussanchez merged commit 7e3ea74 into HashLoad:main Aug 10, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants